package org.flexthinker.binding.value.support
{
    import flash.utils.ByteArray;

    import mx.collections.ArrayCollection;

    import mx.collections.IList;

    import org.hamcrest.assertThat;
    import org.hamcrest.object.equalTo;

    public class ListValueChangeDetectorTest
    {
        private var detector:ListValueChangeDetector;


        public function ListValueChangeDetectorTest()
        {
        }

        [Before]
        public function setUp():void
        {
            detector = new ListValueChangeDetector();
        }

        [Test]
        public function testWithNullValues():void
        {
            var ac1:ArrayCollection = new ArrayCollection([1,2]);
            assertThat("Collections should differ", detector.hasValueChanged(ac1, null), equalTo(true));
            assertThat("Collections should differ", detector.hasValueChanged(null, ac1), equalTo(true));
        }

        [Test]
        public function testWithSameItems():void
        {
            var ac1:ArrayCollection = new ArrayCollection([1,2,3]);
            var ac2:ArrayCollection = new ArrayCollection([1,2,3]);
            assertThat("collections should be similar", detector.hasValueChanged(ac1,ac2), equalTo(false));
        }

        [Test]
        public function testWithFilteredArrayCollection():void
        {
            var ac1:ArrayCollection = new ArrayCollection([1,2,3,4,5,6,7,8,9]);
            var ac2:ArrayCollection = ac1;

            assertThat("collections should be similar", detector.hasValueChanged(ac1,ac2), equalTo(false));

            ac1.filterFunction = filterElements;
            ac1.refresh();
            assertThat("collections should be similar", detector.hasValueChanged(ac1, ac2), equalTo(false));
        }

        private function filterElements(item:Object):Boolean
        {
            return (Number(item) % 2 == 0);
        }

        [Test]
        public function testWithDifferentCollections():void
        {
           var ac1:ArrayCollection = new ArrayCollection([1,2,3,4,5,6,7,8,9]);
           var ac2:ArrayCollection = new ArrayCollection([1,2]);

           assertThat("collections should differ", detector.hasValueChanged(ac1, ac2), equalTo(true));
           assertThat("collections should differ", detector.hasValueChanged(ac2, ac1), equalTo(true));
        }

        [Test]
        public function testWithAddRemoveItems():void
        {
            var o1:Object = {id:1};
            var o2:Object = {id:2};
            var ac1:IList = new ArrayCollection([o1,o2]);
            var ac2:IList = new ArrayCollection(ac1.toArray());
            //ac1.toArray() clones the source of the ac1, creating a new Array instance with same elements.

            assertThat("collections should be similar", detector.hasValueChanged(ac1,ac2), equalTo(false));
            ac2.addItem(10);
            assertThat("collections should differ", detector.hasValueChanged(ac2, ac1), equalTo(true));

            ac2.removeItemAt( ac2.length - 1);
            assertThat("collections should be similar", detector.hasValueChanged(ac1,ac2), equalTo(false));

            ac2.addItem(10);
            assertThat("collections should differ", detector.hasValueChanged(ac2, ac1), equalTo(true));
            ac2.removeItemAt(0);
            assertThat("collections should differ", detector.hasValueChanged(ac2, ac1), equalTo(true));
        }

        [Test]
        public function testWithDuplicatedItems():void
        {
            var o1:Object = {id:1};
            var o2:Object = {id:2};
            var ac1:ArrayCollection = new ArrayCollection([o1,o2]);
            var ac2:ArrayCollection = new ArrayCollection([o1,o1]);

            assertThat("collections should differ", detector.hasValueChanged(ac2, ac1), equalTo(true));
        }

    }
}
